﻿using Newtonsoft.Json;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Svg;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static HookupAppForm.Dto.ResultDto;

namespace HookupAppForm
{
    public class Utils
    {
        public static string GetFileUrl()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "请选择导入文件";
            openFileDialog.Multiselect = false;
            openFileDialog.InitialDirectory = Application.StartupPath;
            openFileDialog.Filter = "所有文件|*.*";
            openFileDialog.ShowDialog();
            return openFileDialog.FileName;
        }
        public static string GetSaveFilePath(string fileName = "")
        {
            SaveFileDialog saveFileDig = new SaveFileDialog();
            saveFileDig.Filter = "Excel Office97-2003(*.xls)|.xls|Excel Office2007及以上(*.xlsx)|*.xlsx";
            saveFileDig.FilterIndex = 0;
            saveFileDig.OverwritePrompt = true;
            saveFileDig.InitialDirectory = Application.StartupPath;
            saveFileDig.FileName = fileName; //默认文件名
            string filePath = null;
            if (saveFileDig.ShowDialog() == DialogResult.OK)
            {
                filePath = saveFileDig.FileName;
            }

            return filePath;
        }
        public static Bitmap ZoomImage(Bitmap bitmap, int destWidth, int destHeight)
        {
            try
            {
                Image sourImage = bitmap;
                int width = 0, height = 0;
                //按比例缩放           
                int sourWidth = sourImage.Width;
                int sourHeight = sourImage.Height;
                if ((sourWidth * destHeight) > (sourHeight * destWidth))
                {
                    width = destWidth;
                    height = (destWidth * sourHeight) / sourWidth;
                }
                else
                {
                    height = destHeight;
                    width = (sourWidth * destHeight) / sourHeight;
                }
                Bitmap destBitmap = new Bitmap(destWidth, destHeight);
                Graphics g = Graphics.FromImage(destBitmap);
                g.Clear(Color.Transparent);
                //设置画布的描绘质量         
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                //g.DrawImage(sourImage, new Rectangle((destWidth - width) / 2, (destHeight - height) / 2, width, height), 0, 0, sourImage.Width, sourImage.Height, GraphicsUnit.Pixel);
                g.DrawImage(sourImage, new Rectangle(12, 0, width, height), 0, 0, sourImage.Width, sourImage.Height, GraphicsUnit.Pixel);

                g.Dispose();
                //设置压缩质量     
                System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters();
                long[] quality = new long[1];
                quality[0] = 100;
                System.Drawing.Imaging.EncoderParameter encoderParam = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
                encoderParams.Param[0] = encoderParam;
                sourImage.Dispose();
                return destBitmap;
            }
            catch
            {
                return bitmap;
            }
        }

        public static Image GetImageFromSVG(string filePath = "", int width = 0, int height = 0)
        {
            try
            {
                //SvgDocument _document = SvgDocument.Open(filePath);
                //int w = width == 0 ? Convert.ToInt32(_document.Width.Value) : width;
                //int h = height == 0 ? Convert.ToInt32(_document.Height.Value) : height;

                //return Utils.ZoomImage(_document.Draw(w, h), w, h);
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }
        public static string GetSourceFromSVG(string filePath)
        {
            try
            {
                //SvgDocument _document = SvgDocument.Open(filePath);
                //return _document.GetXML();
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }
        public static ErrorObject ExceptionHandler(string result)
        {
            try
            {
                ErrorObject resp = JsonConvert.DeserializeObject<ErrorObject>(result);
                if (resp != null && resp.error != null)
                {
                    SysMsg(resp.error.message, MessageBoxIcon.Error);
                    return resp;
                }
                else
                {
                    return null;
                }
            }
            catch
            {
                return null;
            }
        }
        public static ErrorObject ExceptionMsg(string result)
        {
            try
            {
                ErrorObject resp = JsonConvert.DeserializeObject<ErrorObject>(result);
                if (resp != null && resp.error != null)
                {
                    return resp;
                }
                else
                {
                    return null;
                }
            }
            catch
            {
                return null;
            }
        }
        public static object SuccessHandler(string result)
        {
            try
            {
                ErrorObject resp = JsonConvert.DeserializeObject<ErrorObject>(result);
                if (resp != null && resp.result != null)
                {
                    return resp.result;
                }
                else
                {
                    return null;
                }
            }
            catch
            {
                return null;
            }
        }
        public static void SetHeader(DataGridView dgv, FromSetting[] fromSettings, int frozenIndex = -1)
        {

            for (int i = 0; i < dgv.Columns.Count; i++)
            {
                try
                {
                    FromSetting item = fromSettings[i];
                    if (item != null)
                    {
                        dgv.Columns[i].ToolTipText = dgv.Columns[i].Name + "(" + i.ToString() + ")";
                        dgv.Columns[i].ReadOnly = item.IsReadOnly;
                        dgv.Columns[i].Visible = true;
                        if (item.FieldWidth > 0)
                            dgv.Columns[i].Width = item.FieldWidth;
                        dgv.Columns[i].DisplayIndex = item.FieldDisplayIndex == 0 ? i : item.FieldDisplayIndex;
                        if (!string.IsNullOrEmpty(item.FieldFormat))
                        {
                            dgv.Columns[i].DefaultCellStyle.Format = item.FieldFormat;
                        }
                        dgv.Columns[i].DefaultCellStyle.ForeColor = item.ForeColor;
                        dgv.Columns[i].HeaderText = item.FieldDisplay;
                    }
                    else
                    {
                        dgv.Columns[i].Visible = false;
                    }
                }
                catch
                {
                    dgv.Columns[i].Visible = false;
                }
            }
            if (frozenIndex >= 0)
                dgv.Columns[frozenIndex].Frozen = true;

        }
        /// <summary>
        /// 统一MessageBox消息
        /// </summary>
        /// <param name="message"></param>
        /// <param name="icon"></param>
        public static void SysMsg(string message, MessageBoxIcon icon = MessageBoxIcon.Information)
        {
            MessageBox.Show(message, "系统", MessageBoxButtons.OK, icon);
        }

        /// <summary>
        /// 英尺转英寸并返回毫米
        /// </summary>
        /// <param name="size"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static double FtToInMM(string size, string unit)
        {
            try
            {
                string[] sizes = size.Replace("\"", "").Split('/');
                double mm = (double.Parse(sizes[0]) / double.Parse(sizes[1])) * 25.4;
                if (unit.ToLower() == "ft")
                {
                    return 12 * mm;
                }
                if (unit.ToLower() == "cm")
                {
                    return double.Parse(size)*10;
                }
                if (unit.ToLower() == "mm")
                {
                    return double.Parse(size);
                }
                else
                {
                    return mm;
                }
            }
            catch
            {
                return double.Parse(size);
            }
        }


        /// <summary>
        /// 英寸转毫米 并返回毫米
        /// </summary>
        /// <param name="size"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static double ToInMM(string size, string unit)
        {
            try
            {

                string lowUnit = unit.ToLower();
                switch (lowUnit)
                {
                    case "in":
                        try
                        {
                            string[] sizes = size.Replace("\"", "").Split('/');
                            if (sizes.Length > 1)
                            {
                                double mm = (double.Parse(sizes[0]) / double.Parse(sizes[1])) * 25.4;
                                return mm;
                            }
                            else
                            {
                                size = size.Replace("\"", "");
                                return double.Parse(size) * 25.4;
                            }
                            
                        }
                        catch
                        {
                            return double.Parse(size);
                        }
                    case "cm":
                        return double.Parse(size) * 10;

                    default:
                        return double.Parse(size);
                }

            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// 电的kva、kw转换成A  并返回A，，，注意  返回的计算的A
        /// </summary>
        /// <param name="size"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static double ToInA(string size, string unit)
        {
            string lowUnit = unit.ToLower();
            switch (lowUnit)
            {
                case "kva":
                    double kw = double.Parse(size) * 0.8*0.6;
                    double A = kw / 1.732 / 0.8 / 380 * 1000;
                    return A;
                    
                case "kw":
                    double Ax = double.Parse(size)*0.6 / 1.732 / 0.8 / 380 * 1000;
                    return Ax;

                default:
                    return double.Parse(size);
            }

        }

        public static decimal ConvertToLmin(decimal val,string unit = "l/min")
        {
            string lowUnit = unit.ToLower();
            switch (lowUnit)
            {
                case "l/h":
                    return val * Convert.ToDecimal(0.017);
                case "lpm":
                    return val;
                case "slpm":
                    return val;
                case "scfm":
                    return val * Convert.ToDecimal(28.311);
                case "cfm":
                    return val * Convert.ToDecimal(28.311);
                case "cmh":
                    return val * Convert.ToDecimal(16.67);
                case "cmm":
                    return val * Convert.ToDecimal(1000);
                case "m³/h":
                    return val * Convert.ToDecimal(16.7);
                case "m³/min":
                    return val * Convert.ToDecimal(1000);
                case "nm³/h":
                    return val * Convert.ToDecimal(16.7);
                case "clm":
                    return val;
                case "nl/min":
                    return val;
                case "sccm":
                    return val * Convert.ToDecimal(0.001);
                
                default:
                    return val;
            }
        }


        /// <summary>
        /// 流量换算，全部换算为 m³/s 单位值
        /// </summary>
        /// <param name="val"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static decimal ConvertFlow(decimal val, string unit = "m³/min")
        {
            string lowUnit = unit.ToLower();
            switch (lowUnit)
            {
                case "m³/hr":
                    return val * Convert.ToDecimal(0.0167);
                case "lpm":
                    return val * Convert.ToDecimal(0.001);
                case "l/min":
                    return val * Convert.ToDecimal(0.001);
                case "cmh":
                    return val * Convert.ToDecimal(0.0167);
                case "cmm":
                    return val;
                case "clm":
                    return val * Convert.ToDecimal(0.001);
                case "cfm":
                    return val * Convert.ToDecimal(0.028);
                default:
                    return val;
            }
        }
        /// <summary>
        /// 压强换算，全部换算为Pa单位值
        /// </summary>
        /// <param name="val"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static decimal ConvertPress(decimal val, string unit = "Pa")
        {
            string lowUnit = unit.ToLower();
            switch (lowUnit)
            {
                case "mpa":
                    return val * Convert.ToDecimal(1000000);
                case "kpa":
                    return val * Convert.ToDecimal(1000);
                default:
                    return val;
            }
        }
        /// <summary>
        /// 功率换算，全部换算为W单位值
        /// </summary>
        /// <param name="val"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static decimal ConvertWatt(decimal val, string unit = "W")
        {
            string lowUnit = unit.ToLower();
            switch (lowUnit)
            {
                case "kw":
                    return val * Convert.ToDecimal(1000);
                default:
                    return val;
            }
        }

        public static void OpenFile(string path)
        {
            Process process = new Process();
            ProcessStartInfo processStartInfo = new ProcessStartInfo(path);
            process.StartInfo = processStartInfo;
            try
            {
                process.Start();
                try
                {
                    // process.WaitForExit();
                }
                catch (Exception ex)
                {
                    SysMsg(ex.Message, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                SysMsg(ex.Message, MessageBoxIcon.Error);
            }
            finally
            {
                try
                {
                    if (process != null)
                    {
                        process.Close();
                        process = null;
                    }
                }
                catch { }
            }
        }

        //地球半径，单位米
        private const double EARTH_RADIUS = 6378137;
        /// <summary>
        /// 计算两点位置的距离，返回两点的距离，单位 米
        /// 该公式为GOOGLE提供，误差小于0.2米
        /// </summary>
        /// <param name="lat1">第一点纬度</param>
        /// <param name="lng1">第一点经度</param>
        /// <param name="lat2">第二点纬度</param>
        /// <param name="lng2">第二点经度</param>
        /// <returns></returns>
        public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
        {
            double radLat1 = Rad(lat1);
            double radLng1 = Rad(lng1);
            double radLat2 = Rad(lat2);
            double radLng2 = Rad(lng2);
            double a = radLat1 - radLat2;
            double b = radLng1 - radLng2;
            double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
            return result;
        }

        /// <summary>
        /// 经纬度转化成弧度
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double Rad(double d)
        {
            return (double)d * Math.PI / 180d;
        }

        public static double GetDistance(int A_x, int A_y, int B_x, int B_y)
        {
            int x = System.Math.Abs(B_x - A_x);
            int y = System.Math.Abs(B_y - A_y);
            return Math.Sqrt(x * x + y * y);
        }

        public static DataTable ExcelToTable(string file)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            DataTable dt = new DataTable();
            IWorkbook workbook;
            string fileExt = Path.GetExtension(file).ToLower();
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                //XSSFWorkbook 适用XLSX格式，HSSFWorkbook 适用XLS格式
                if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(fs); }
                else if (fileExt == ".xls") { workbook = new HSSFWorkbook(fs); }
                else { workbook = null; }

                if (workbook == null) { return null; }
                ISheet sheet = workbook.GetSheetAt(0);

                //表头  
                IRow header = sheet.GetRow(sheet.FirstRowNum);
                List<int> columns = new List<int>();
                for (int i = 0; i < header.LastCellNum; i++)
                {
                    object obj = GetValueType(header.GetCell(i));
                    if (obj == null || obj.ToString() == string.Empty)
                    {
                        dt.Columns.Add(new DataColumn("Columns" + i.ToString()));
                    }
                    else
                        dt.Columns.Add(new DataColumn(obj.ToString()));
                    columns.Add(i);
                }
                //数据  
                for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++)
                {
                    DataRow dr = dt.NewRow();
                    bool hasValue = false;
                    foreach (int j in columns)
                    {
                        dr[j] = GetValueType(sheet.GetRow(i).GetCell(j));
                        if (dr[j] != null && dr[j].ToString() != string.Empty)
                        {
                            hasValue = true;
                        }
                    }
                    if (hasValue)
                    {
                        dt.Rows.Add(dr);
                    }
                }
            }
            return dt;
        }
        public static IList<T> ExcelToList<T>(string file) where T : class, new()
        {
            IList<T> list = new List<T>();
            try
            {
                IWorkbook workbook;
                string fileExt = Path.GetExtension(file).ToLower();
                using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                {
                    if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(fs); } else if (fileExt == ".xls") { workbook = new HSSFWorkbook(fs); } else { workbook = null; }
                    if (workbook == null) { return null; }
                    ISheet sheet = workbook.GetSheetAt(0);

                    IRow header = sheet.GetRow(sheet.FirstRowNum);
                    string[] columns = new string[header.LastCellNum];
                    for (int i = 0; i < header.LastCellNum; i++)
                    {
                        object obj = GetValueType(header.GetCell(i));
                        if (obj == null || obj.ToString() == string.Empty)
                        {
                            columns[i] = "Columns" + i.ToString();
                        }
                        else
                            columns[i] = obj.ToString();
                    }
                    //遍历每一行数据
                    for (int i = sheet.FirstRowNum + 1, len = sheet.LastRowNum + 1; i < len; i++)
                    {
                        T t = new T();
                        IRow row = sheet.GetRow(i);

                        for (int j = 0, len2 = columns.Length; j < len2; j++)
                        {
                            ICell cell = row.GetCell(j);
                            object cellValue = GetValueType(cell);
                            var prop = typeof(T).GetProperty(columns[j]);
                            string vtype = prop.PropertyType.Name.ToLower();
                            if (vtype == "double")
                                prop.SetValue(t, Convert.ToDouble(cellValue), null);
                            else if (vtype == "decimal")
                                prop.SetValue(t, Convert.ToDecimal(cellValue), null);
                            else if (vtype == "int32")
                                prop.SetValue(t, Convert.ToInt32(cellValue), null);
                            else if (vtype == "long")
                                prop.SetValue(t, Convert.ToInt32(cellValue), null);
                            else
                                prop.SetValue(t, cellValue, null);
                        }
                        list.Add(t);
                    }
                }
            }
            catch (Exception ex)
            {
                SysMsg(ex.Message, MessageBoxIcon.Error);
            }
            return list;
        }
        private static object GetValueType(ICell cell)
        {
            if (cell == null)
                return null;
            switch (cell.CellType)
            {
                case CellType.Blank: //BLANK:  
                    return null;
                case CellType.Boolean: //BOOLEAN:  
                    return cell.BooleanCellValue;
                case CellType.Numeric: //NUMERIC:  
                    return cell.NumericCellValue;
                case CellType.String: //STRING:  
                    return cell.StringCellValue;
                case CellType.Error: //ERROR:  
                    return cell.ErrorCellValue;
                case CellType.Formula: //FORMULA:  
                default:
                    return "=" + cell.CellFormula;
            }
        }

        public static decimal CvtDec(object val)
        {
            try
            {
                return Convert.ToDecimal(val);
            }
            catch
            {
                return 0;
            }
        }

        public static string ExportExcel(DataGridView dgv, string filePath, string fileName = "")
        {
            if (string.IsNullOrEmpty(filePath))
            {
                filePath = GetSaveFilePath(fileName);
            }
            if (string.IsNullOrEmpty(filePath)) return null;
            try
            {
                //创建Excel文件的对象  
                NPOI.HSSF.UserModel.HSSFWorkbook book = new NPOI.HSSF.UserModel.HSSFWorkbook();
                int pageSize = 60000;
                int sheetNum = dgv.Rows.Count / pageSize;
                if (dgv.Rows.Count % pageSize > 0)
                    sheetNum = sheetNum + 1;

                for (int k = 1; k <= sheetNum; k++)
                {
                    NPOI.SS.UserModel.ISheet sheet1 = book.CreateSheet("Sheet" + k);
                    NPOI.SS.UserModel.IRow row1 = sheet1.CreateRow(0);
                    for (int i = 0; i < dgv.Columns.Count; i++)
                    {
                        row1.CreateCell(i).SetCellValue(dgv.Columns[i].HeaderCell.Value.ToString());
                    }

                    int startIndex = (k - 1) * pageSize;
                    startIndex = k == 1 ? startIndex : startIndex + 1;

                    int endIndex = k * pageSize;
                    endIndex = endIndex > dgv.Rows.Count ? dgv.Rows.Count : endIndex;

                    int rowStart = startIndex;
                    for (int i = 0; i < endIndex - startIndex; i++)
                    {
                        NPOI.SS.UserModel.IRow rowtemp = sheet1.CreateRow(i + 1);
                        for (int j = 0; j < dgv.Columns.Count; j++)
                        {
                            if (dgv.Rows[rowStart].Cells[j].Value != null)
                            {
                                rowtemp.CreateCell(j).SetCellValue(dgv.Rows[rowStart].Cells[j].Value.ToString().Trim());
                            }
                        }
                        rowStart++;
                    }
                }

                FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                book.Write(fs);
                fs.Dispose();
                book = null;
            }
            catch (Exception err)
            {
                SysMsg(err.Message, MessageBoxIcon.Error);
            }
            return filePath;
        }
    }
}
